package com.you.weixinpay.utils;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.you.weixinpay.domain.entity.TRefundInfo;
import com.you.weixinpay.enums.AliPayNotifyType;
import com.you.weixinpay.properties.AliPayProperties;
import com.you.weixinpay.service.TRefundInfoService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Slf4j
@Component
public class AliPayNativeUtils {
    @Resource
    private AlipayClient alipayClient;

    @Resource
    private AliPayProperties aliPayProperties;

    @Resource
    private TRefundInfoService refundInfoService;

    /**
     * 创建支付宝支付订单
     *
     * @param orderNo  商户订单号
     * @param totalFee 订单金额(单位：元)
     * @param subject  订单标题
     * @return 支付宝支付表单HTML
     * @throws AlipayApiException 支付宝API异常
     */
    public String createPayment(String orderNo, BigDecimal totalFee, String subject) throws AlipayApiException {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

        // 配置通知地址和返回地址
        request.setNotifyUrl(aliPayProperties.getNotifyUrl().concat(AliPayNotifyType.ALI_NOTIFY.getType()));
        request.setReturnUrl(aliPayProperties.getReturnUrl());

        // 组装业务参数
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderNo);
        bizContent.put("total_amount", totalFee);
        bizContent.put("subject", subject);
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");

        request.setBizContent(bizContent.toString());

        // 执行请求
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

        if (response.isSuccess()) {
            log.info("调用成功，返回结果 ===> " + response.getBody());
            return response.getBody();
        } else {
            log.error("支付宝支付创建失败，订单号：{}，错误码：{}，错误信息：{}",
                    orderNo, response.getCode(), response.getMsg());
            throw new AlipayApiException("支付宝支付创建失败：" + response.getMsg());
        }
    }

    /**
     * 关闭订单
     *
     * @param orderNo 商户订单号
     * @throws AlipayApiException 支付宝API异常
     */
    public void closeOrder(String orderNo) throws AlipayApiException {
        log.info("关单接口的调用，订单号 ===> {}", orderNo);
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderNo);
        request.setBizContent(bizContent.toString());
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            log.info("调用成功，返回结果 ===> " + response.getBody());
        } else {
            log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
        }
    }


    /**
     * 查询支付宝订单状态
     * @param orderNo 商户订单号
     * @return 支付宝返回的订单信息(JSON格式)，如果订单不存在返回null
     * @throws AlipayApiException 支付宝API异常
     */
    public String queryOrder(String orderNo) throws AlipayApiException {
        log.info("查询支付宝订单，订单号：{}", orderNo);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderNo);
        request.setBizContent(bizContent.toString());

        AlipayTradeQueryResponse response = alipayClient.execute(request);

        if (response.isSuccess()) {
            log.info("支付宝订单查询成功，订单号：{}，返回结果：{}", orderNo, response.getBody());
            return response.getBody();
        } else {
            log.warn("支付宝订单查询失败，订单号：{}，错误码：{}，错误信息：{}",
                    orderNo, response.getCode(), response.getMsg());
            return null; // 订单不存在
        }
    }

    /**
     * 1.封装完整的退款流程
     * @param orderNo 商户订单号
     * @param refundAmount 退款金额
     * @param refundReason 退款原因
     * @return 退款是否成功
     */
    public AlipayTradeRefundResponse refund(String orderNo, BigDecimal refundAmount, String refundReason) {
        try {
            // 执行退款，调用一个个辅助方法
            return executeRefund(orderNo, refundAmount, refundReason);
        } catch (AlipayApiException e) {
            log.error("支付宝退款API调用异常", e);
            return null;
        }
    }

    /**
     * 2.执行支付宝退款
     * @param orderNo 商户订单号
     * @param refundAmount 退款金额
     * @param refundReason 退款原因(可选)
     * @return 退款响应结果
     * @throws AlipayApiException 支付宝API异常
     */
    public AlipayTradeRefundResponse executeRefund(String orderNo, BigDecimal refundAmount, String refundReason)
            throws AlipayApiException {
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderNo);
        bizContent.put("refund_amount", refundAmount);

        if (StringUtils.isNotBlank(refundReason)) {
            bizContent.put("refund_reason", refundReason);
        }

        request.setBizContent(bizContent.toString());

        log.info("发起支付宝退款请求，订单号: {}, 金额: {}, 原因: {}", orderNo, refundAmount, refundReason);

        return alipayClient.execute(request);
    }

    /**
     * 3.处理退款响应
     * @param response 支付宝退款响应
     * @return 处理结果
     */
    public boolean processRefundResponse(AlipayTradeRefundResponse response) {
        if (response == null) {
            log.error("支付宝【退款响应为空】");
            return false;
        }
        if (response.isSuccess()) {
            log.info("支付宝【退款成功】，返回结果: {}", response.getBody());
            return true;
        } else {
            log.error("支付宝【退款失败】，返回码: {}, 返回描述: {}", response.getCode(), response.getMsg());
            return false;
        }
    }


    /**
     * 查询支付宝退款状态
     * @param orderNo 商户订单号
     * @return 退款查询结果(JSON格式)，如果查询失败返回null
     */
    public String queryRefund(String orderNo) {
        try {
             TRefundInfo order = refundInfoService.getOne(new LambdaQueryWrapper<TRefundInfo>().eq(TRefundInfo::getOrderNo, orderNo));
             String refundOrderNo = order.getRefundNo();
             AlipayTradeFastpayRefundQueryResponse response = executeRefundQuery(orderNo, refundOrderNo);
            return processRefundQueryResponse(response);
        } catch (AlipayApiException e) {
            log.error("支付宝退款查询API调用异常", e);
            return null;
        }
    }

    /**
     * 执行支付宝退款查询
     * @param orderNo 商户订单号
     * @param refundOrderNo 退款请求号
     * @return 退款查询响应
     * @throws AlipayApiException 支付宝API异常
     */
    public AlipayTradeFastpayRefundQueryResponse executeRefundQuery(String orderNo, String refundOrderNo)
            throws AlipayApiException {
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderNo);
        bizContent.put("out_request_no", refundOrderNo);

        request.setBizContent(bizContent.toString());

        log.info("发起支付宝退款查询，订单号: {}, 退款单号: {}", orderNo, refundOrderNo);

        return alipayClient.execute(request);
    }

    /**
     * 处理退款查询响应
     * @param response 退款查询响应
     * @return 处理后的退款信息(JSON格式)
     */
    public String processRefundQueryResponse(AlipayTradeFastpayRefundQueryResponse response) {
        if (response == null) {
            log.error("支付宝【退款查询响应为空】");
            return null;
        }

        if (response.isSuccess()) {
            log.info("支付宝【退款查询成功】，返回结果: {}", response.getBody());

            // 构建返回的退款信息
            JSONObject result = new JSONObject();
            result.put("code", "10000"); // 成功码
            result.put("msg", "Success");
            //备注：【以下信息支付宝没有发送】
            result.put("orderNo", response.getOutTradeNo());
            result.put("refundOrderNo", response.getOutRequestNo());
            result.put("refundAmount", response.getRefundAmount());
            result.put("refundStatus", response.getRefundStatus());
            result.put("gmtRefundPay", response.getGmtRefundPay());

            return result.toJSONString();
        } else {
            log.error("支付宝【退款查询失败】，返回码: {}, 返回描述: {}",
                    response.getCode(), response.getMsg());

            JSONObject result = new JSONObject();
            result.put("code", response.getCode());
            result.put("msg", response.getMsg());
            result.put("subCode", response.getSubCode());
            result.put("subMsg", response.getSubMsg());

            return result.toJSONString();
        }
    }
}
